#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RunAllSide-Channel AttackTest
"""

import os
import sys
import unittest
import time
from pathlib import Path

# Add父DirectoryToPath
sys.path.insert(0, str(Path(__file__).parent.parent))

# 导入AllTestModule
from tests.test_basic_attacks import TestBasicAttacks, TestAttackResults
from tests.test_algorithm_attacks import TestAlgorithmSpecificAttacks, TestAttackIntegration
from tests.test_attack_manager import TestAttackManager, TestAttackConfiguration, TestCreateAttackManager


def check_test_data():
    """CheckTestDataYesNo存In"""
    test_data_dir = Path(__file__).parent.parent / "power_traces"
    required_files = [
        test_data_dir / "aes_test_traces.npz",
        test_data_dir / "sm4_test_traces.npz"
    ]
    
    missing_files = []
    for file_path in required_files:
        if not file_path.exists():
            missing_files.append(file_path)
    
    if missing_files:
        print("[FAIL] 缺少TestDataFile:")
        for file_path in missing_files:
            print(f"   {file_path}")
        print("\n请Run以下CommandGenerateTestData:")
        print("cd /home/ga4ss/workspace/j0ker/xchip")
        print("python3 tools/power_trace_generator.py -a aes -n 50 -o side_channel_attacks/power_traces/aes_test_traces.npz --noise")
        print("python3 tools/power_trace_generator.py -a sm4 -n 30 -o side_channel_attacks/power_traces/sm4_test_traces.npz --noise")
        return False
    
    print("[OK] AllTestDataFile存In")
    return True


def run_test_suite(test_classes, suite_name):
    """RunTest套件"""
    print(f"\n{'='*60}")
    print(f"Run {suite_name}")
    print(f"{'='*60}")
    
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()
    
    # AddTestClass
    for test_class in test_classes:
        suite.addTests(loader.loadTestsFromTestCase(test_class))
    
    # RunTest
    runner = unittest.TextTestRunner(verbosity=2, stream=sys.stdout)
    start_time = time.time()
    result = runner.run(suite)
    end_time = time.time()
    
    # OutputResult
    print(f"\n{suite_name} Result:")
    print(f"  - Run时间: {end_time - start_time:.2f}秒")
    print(f"  - Test总数: {result.testsRun}")
    print(f"  - Success: {result.testsRun - len(result.failures) - len(result.errors)}")
    print(f"  - Failed: {len(result.failures)}")
    print(f"  - Error: {len(result.errors)}")
    
    if result.failures:
        print(f"\nFailed的Test:")
        for test, traceback in result.failures:
            print(f"  - {test}")
    
    if result.errors:
        print(f"\nError的Test:")
        for test, traceback in result.errors:
            print(f"  - {test}")
    
    return result


def main():
    """主Function"""
    print("Side-Channel Attack框架 - CompleteTest套件")
    print("="*60)
    
    # CheckTestData
    if not check_test_data():
        return 1
    
    # 定义Test套件
    test_suites = [
        {
            'name': '基础AttackTest',
            'classes': [TestBasicAttacks, TestAttackResults]
        },
        {
            'name': 'Algorithm特定AttackTest',
            'classes': [TestAlgorithmSpecificAttacks, TestAttackIntegration]
        },
        {
            'name': 'Attack管理器Test',
            'classes': [TestAttackManager, TestAttackConfiguration, TestCreateAttackManager]
        }
    ]
    
    # RunAllTest套件
    all_results = []
    total_start_time = time.time()
    
    for suite_info in test_suites:
        result = run_test_suite(suite_info['classes'], suite_info['name'])
        all_results.append((suite_info['name'], result))
    
    total_end_time = time.time()
    
    # Output总体Result
    print(f"\n{'='*60}")
    print("总体TestResult")
    print(f"{'='*60}")
    
    total_tests = 0
    total_failures = 0
    total_errors = 0
    successful_suites = 0
    
    for suite_name, result in all_results:
        total_tests += result.testsRun
        total_failures += len(result.failures)
        total_errors += len(result.errors)
        
        if result.wasSuccessful():
            successful_suites += 1
            status = "[OK] Through"
        else:
            status = "[FAIL] Failed"
        
        print(f"{suite_name:<20} {status}")
    
    print(f"\n总体统计:")
    print(f"  - 总Run时间: {total_end_time - total_start_time:.2f}秒")
    print(f"  - Test套件: {successful_suites}/{len(all_results)} Through")
    print(f"  - Test用例: {total_tests - total_failures - total_errors}/{total_tests} Through")
    print(f"  - Success率: {(total_tests - total_failures - total_errors)/total_tests*100:.1f}%")
    
    if total_failures > 0 or total_errors > 0:
        print(f"  - Failed: {total_failures}")
        print(f"  - Error: {total_errors}")
        print(f"\n[FAIL] Test套件未完全Through")
        return 1
    else:
        print(f"\n[Success] AllTestThrough!")
        return 0


if __name__ == '__main__':
    try:
        exit_code = main()
        sys.exit(exit_code)
    except KeyboardInterrupt:
        print("\n[WARNING] Test被用户Interrupt")
        sys.exit(1)
    except Exception as e:
        print(f"\n[FAIL] TestRunFailed: {e}")
        sys.exit(1)
